import _ from "lodash";

export const isInitNumber = (value: any) => _.isNumber(value) && !_.isNaN(value);

export const isInitString = (value: any) => _.isString(value) && value.length > 0;

export const isInitArray = (value: any) => _.isArray(value) && value.length > 0;

export const isFormalEqual = (l: any, r: any) => _.toString(l) === _.toString(r);

export const limitValue = (value: number, left: number, right: number) =>
  Math.max(left, Math.min(value, right));

export const objectFrom = (...args: Array<any>) => Object.assign({}, ...args);

export const rectEqual = (left: any, right: any) => {
  if (left instanceof DOMRect && right instanceof DOMRect) {
    if (left.width === right.width && left.height === right.height) {
      return true
    }
  }
  return false;
};

export const switchValue = (
  value: any,
  option: Array<any>,
  key: string,
  deal?: Function
) => {
  let defaultValue = {};
  let result: any = undefined;
  _.forEach(option, (item) => {
    if (item.default) {
      defaultValue = _.clone(item);
    }
    if (!result) {
      if (deal) {
        if (typeof deal === "string") {
          if (deal === "toString") {
            if (_.toString(item[key || "value"]) === _.toString(value)) {
              result = item;
            }
          }
        } else if (deal(item[key || "value"]) === deal(value)) {
          result = item;
        }
      } else {
        if (item[key || "value"] === value) {
          result = item;
        }
      }
    }
  });
  return result || defaultValue || {};
};

// 方便统一处理错误信息
export const DispatchResult = (body: any, options: any) => {
  if (body) {
    if (body.code === 200) {
      options.onSuccess && options.onSuccess(body.data, body.message);
    } else {
      options.onError && options.onError(body, body.message);
    }
  }
};

export const globalInstall = (app: any, fn: any, name: any) => {
  fn._context = app._context;
  app.config.globalProperties[name] = fn;
};

export const RouteParams = (config: any) => {
  if (typeof config === "object") {
    if (_.isArray(config)) {
      return config.reduce((res, name) => {
        res[name] = function () {
          return _.get(this.$route, `params[${name}]`);
        };
        return res;
      }, {});
    } else {
      return Object.keys(config).reduce((res: any, afterName: any) => {
        const options = config[afterName];
        let name = options;
        let type: any = String;
        if (_.isArray(options)) {
          name = options[0];
          type = options[1];
        }
        res[afterName] = function () {
          let value = _.get(this.$route, `params[${name}]`);
          if (type === Number) {
            value = _.toNumber(value);
          }
          return value;
        };
        return res;
      }, {});
    }
  }
  return {};
};

export class pageHelper {
  currentPage = 1;
  pageSize = 10;
  totalNum = 0;

  set(params: any) {
    let totalNum = parseInt(params["totalNum"]);
    if (!isInitNumber(totalNum)) {
      totalNum = 0;
    }
    this.totalNum = totalNum;
    let pageSize = parseInt(params["pageSize"]);
    if (!isInitNumber(pageSize)) {
      pageSize = 10;
    }
    this.pageSize = pageSize;
    let currentPage = parseInt(params["currentPage"]);
    if (!isInitNumber(currentPage)) {
      currentPage = 1;
    }
    this.setCurrentPage(currentPage);
  }

  setCurrentPage(currentPage: number) {
    const maxPage = Math.max(Math.ceil(this.totalNum / this.pageSize), 1);
    this.currentPage = limitValue(currentPage, 1, maxPage);
  }

  data() {
    this.setCurrentPage(this.currentPage);
    return {
      currentPage: this.currentPage,
      pageSize: this.pageSize,
    };
  }
}

export const calculateSwitch = (num: any, data: any) => {
  // 分参考值和输入值，如果二者都是数字，则两个值之中取最小的
  // 或者输入值是百分比，则对参考值进行运算，算出输入值对应的结果
  if (typeof data === "number") {
    return Math.min(num, data);
  } else if (typeof data === "string") {
    try {
      const text = data.match(/[0-9]+(?=%)/g)
      const percentage = text ? _.toNumber(text[0]) : undefined;
      if (_.isNumber(percentage)) {
        return (num * percentage) / 100;
      }
    } catch (error) { /* empty */ }
  }
  return num;
};

export const merge = function (target: any, ...args: Array<any>) {
  for (let i = 0, j = args.length; i < j; i++) {
    const source = args[i] || {};

    for (const prop in source) {
      if (Object.prototype.hasOwnProperty.call(source, prop)) {
        const value = source[prop];
        target[prop] = value;
      }
    }
  }

  return target;
};

export function rafThrottle(fn: Function) {
  let locked = false;
  return function (this: any, ...args: Array<any>) {
    if (locked) return;
    locked = true;
    const self = this;
    window.requestAnimationFrame(function () {
      fn.apply(self, args);
      locked = false;
    });
  };
}

export const getRelativeOffset = (el: any, parent: any) => {
  let offsetTop = 0,
    offsetLeft = 0;
  while (el && el.tagName !== "BODY" && el !== parent) {
    offsetTop += el.offsetTop - el.scrollTop;
    offsetLeft += el.offsetLeft - el.scrollLeft;
    el = el.offsetParent;
  }
  return {
    top: offsetTop,
    left: offsetLeft,
  };
};
